package com.juyu.miliao.api.service;

import com.alibaba.fastjson.JSONObject;
import com.juyu.miliao.api.domain.vo.WxUserInfoVo;
import com.juyu.miliao.api.util.HttpUtil;
import com.juyu.miliao.api.util.RedisKeys;
import com.juyu.miliao.common.exception.ConsumeRuntimeException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.text.StrSubstitutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author xuanqicheng
 * @create 2019-26-15:58
 */
@Service
@Slf4j
public class WxUserInfoService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public static final String APP_ID = "APPID";
    //历史：wxb9a8f6a8a088d51f
    public static final String APP_ID_VALUE = "wx30cd4a5bc6eb8897";

    public static final String APP_SECRET = "APPSECRET";
    //历史：fa7aa9716a69ebc953d3552313179e1b
    public static final String APP_SECRET_VALUE = "036ce987e376ec61efa1232b4468171f";

    public static final String CODE = "CODE";

    private static final String ACCESS_TOKEN_CODE = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=${APPID}&secret=${APPSECRET}&code=${CODE}&grant_type=authorization_code";

    private static final String ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${APPSECRET}";

    private static final String USER_INFO = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=${ACCESS_TOKEN}&openid=${OPENID}&lang=zh_CN";

    /* by:wbf 微信分享赚钱-寻寻公众号参数*/
    public static final String SHARE_APP_ID_VALUE = "wx30cd4a5bc6eb8897";
    /* by:wbf 微信分享赚钱-寻寻公众号参数*/
    public static final String SHARE_APP_SECRET_VALUE = "036ce987e376ec61efa1232b4468171f";

    public String getOpenId(String code, String state) {

        Map<String, String> map = new HashMap<>(0);
        map.put(APP_ID, APP_ID_VALUE);
        map.put(APP_SECRET, APP_SECRET_VALUE);
        map.put(CODE, code);
        String url = urlReplace(ACCESS_TOKEN_CODE, map);
        log.info("获取网页token的URL：{}", url);
        String res = HttpUtil.httpGetUtil(url);
        log.info("获取网页token的返回：{}", res);
        if(StringUtils.isNotBlank(res)){
            JSONObject token = JSONObject.parseObject(res);
            if (token.containsKey("errcode")) {
                throw new ConsumeRuntimeException("获取openId错误");
            }
            String openId = token.getString("openid");
            log.info("用户OpenId信息：{}", openId);

            return openId;
        }else{
            throw new ConsumeRuntimeException("Http请求微信公众号获取OPENID息错误");
        }

    }


    /**
     * 获取access_token,access_token设置缓存时间90分钟
     */
    public String getAccessToken(){
        String key = RedisKeys.WX_ACCESS_TOKEN_CODE.getValue(APP_ID_VALUE,APP_SECRET_VALUE);
        if(stringRedisTemplate.hasKey(key)){
            String accessToken = stringRedisTemplate.opsForValue().get(key);
            return accessToken;
        }else{
            Map<String, String> parameMap = new HashMap<>(2);
            parameMap.put(APP_SECRET, APP_SECRET_VALUE);
            parameMap.put(APP_ID, APP_ID_VALUE);

            String url = urlReplace(ACCESS_TOKEN, parameMap);

            log.info("获取access_token的URL：{}", url);

            String res = HttpUtil.httpGetUtil(url);

            log.info("获取access_token的返回：{}", res);

            if(StringUtils.isNotBlank(res)){

                JSONObject accessTokenJson = JSONObject.parseObject(res);
                if (accessTokenJson.containsKey("errcode")) {

                    throw new ConsumeRuntimeException("获取openId错误");
                }

                String accessToken = accessTokenJson.getString("access_token");

                stringRedisTemplate.opsForValue().set(key,accessToken,90, TimeUnit.MINUTES);

                return accessToken;
            }else{
                throw new ConsumeRuntimeException("Http请求微信公众号获取用户信息错误");
            }

        }
    }

    /**
     * 根据openId 获取用户信息
     * @param openId
     * @return
     */
    public WxUserInfoVo getWxUserInfo(String openId){
        String accessToken = getAccessToken();

        Map<String, String> parameMap = new HashMap<>(2);
        parameMap.put("ACCESS_TOKEN",accessToken);
        parameMap.put("OPENID",openId);

        String url = urlReplace(USER_INFO,parameMap);
        log.info("获取用户信息的URL：{}", url);
        String res = HttpUtil.httpGetUtil(url);
        log.info("获取用户信息的返回：{}", res);
        if(StringUtils.isNotBlank(res)){

            JSONObject userInfoJson = JSONObject.parseObject(res);

            if(!userInfoJson.containsKey("errcode")){

                return JSONObject.parseObject(res,WxUserInfoVo.class);
            }else{
                int erroCode = userInfoJson.getIntValue("errcode");
                String errMsg = userInfoJson.getString("errmsg");
                throw new ConsumeRuntimeException("根据OPENID获取用户信息错误：erroCode="+erroCode+"|errMsg="+errMsg);
            }
        }else{
            throw new ConsumeRuntimeException("HTTP请求微信获取用户信息异常");
        }
    }

    /**
     * 将URL中的模板参数用实际值替换
     * @param url   url
     * @param parms 参数
     * @return 替换参数后的url
     */
    public static String urlReplace(String url, Map<String, String> parms) {
        if (StringUtils.isNotBlank(url) && null != parms) {
            StrSubstitutor strsub = new StrSubstitutor(parms);
            url = strsub.replace(url);
        }
        return url;
    }

    public String getRedirectUrl(String wxRedirectUrl) throws UnsupportedEncodingException {
        //http://test.api.goliaoyou.com/wx/openId
        String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + APP_ID_VALUE
                + "&redirect_uri=" + URLEncoder.encode(wxRedirectUrl,"UTF-8")
                + "&response_type=code"
                + "&scope=snsapi_userinfo"
                + "&state=STATE#wechat_redirect";
        return url;
    }

    public Object getShareOpenId(String code) {
        Map<String, String> map = new HashMap<>(0);
        map.put(APP_ID, SHARE_APP_ID_VALUE);
        map.put(APP_SECRET, SHARE_APP_SECRET_VALUE);
        map.put(CODE, code);
        String url = urlReplace(ACCESS_TOKEN_CODE, map);
        log.info("getShareOpenId-----获取网页token的URL：{}", url);
        String res = HttpUtil.httpGetUtil(url);
        log.info("getShareOpenId-----获取网页token的返回：{}", res);
        return res;
    }

}
